﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace RaisingStudio.SmallProgram.Library
{
    public static class Platform
    {
        private static Dictionary<string, int> _nameGenerationMap = new Dictionary<string, int>();
        private static Dictionary<string, object> _objectMap = new Dictionary<string, object>();

        public static Primitive CreateInstance(Primitive typeName)
        {
            try
            {
                object value = Activator.CreateInstance(Type.GetType((string)typeName));
                string name = GenerateNewName("Instance");
                _objectMap[name] = value;
                return name;
            }
            catch
            {
                return "ERROR";
            }
        }

        internal static string GenerateNewName(string prefix)
        {
            int num = 0;
            _nameGenerationMap.TryGetValue(prefix, out num);
            num++;
            _nameGenerationMap[prefix] = num;
            return (prefix + num.ToString());
        }

        public static Primitive InvokeInstanceMethod(Primitive instanceId, Primitive methodName, Primitive argumentsStackName)
        {
            try
            {
                object instance = _objectMap[(string)instanceId];
                MethodInfo method = instance.GetType().GetMethod((string)methodName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
                int count = (int)Stack.GetCount(argumentsStackName);
                if (method.GetParameters().Length == count)
                {
                    List<object> list = new List<object>();
                    for (int i = count - 1; i >= 0; i--)
                    {
                        list[i] = Stack.PopValue(argumentsStackName);
                    }
                    return new Primitive(method.Invoke(instance, list.ToArray()));
                }
                return "ERROR";
            }
            catch
            {
                return "ERROR";
            }
        }

        public static Primitive InvokeStaticMethod(Primitive typeName, Primitive methodName, Primitive argumentsStackName)
        {
            try
            {
                MethodInfo method = Type.GetType((string)typeName).GetMethod((string)methodName, BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase);
                int count = (int)Stack.GetCount(argumentsStackName);
                if (method.GetParameters().Length == count)
                {
                    List<object> list = new List<object>();
                    for (int i = count - 1; i >= 0; i--)
                    {
                        list[i] = Stack.PopValue(argumentsStackName);
                    }
                    return new Primitive(method.Invoke(null, list.ToArray()));
                }
                return "ERROR";
            }
            catch
            {
                return "ERROR";
            }
        }
    }
}

